/*
 * Class Learning AI
 * 
 * The implemented Learning AI plays the game as the opponent, making move decisions based on learning.  
 * It returns an English description of the reasoning behind the learning system.
 */

/**
 *
 * @author Jill Greczek, Julio Montero, Brandon Jarratt
 */

import javax.swing.JTextArea;

public class team2_LearningAI extends team2_AI
{
	/** Keeps track of the number of optimal moves the player has made. */
	private int goodMoves;
	
	/** Depth adjustment */
	private int depthAdjust;
	
	/** Message log */
	JTextArea messageLog;
	
	/** Keeps track of depthAdjust */
	boolean depthAdjusted;
	
    /**
     * Construct a learning AI system for playing Othello.
     * @param player the player color
     */
    public team2_LearningAI(Player player)
    {
	// Ignore the difficulty level for the learning system
        super(player, Difficulty.EASY);
        goodMoves = 0;
        depthAdjust = 2;
        messageLog = new JTextArea();
        depthAdjusted = false;
    }
    
    public team2_LearningAI(Player player, JTextArea textArea)
    {
	// Ignore the difficulty level for the learning system
        super(player, Difficulty.EASY);
        goodMoves = 0;
        depthAdjust = 2;
        messageLog = textArea;
        depthAdjusted = false;
    }
    
    /** An accessor so the LearningAI can write to the GUI. */
    public void setTextArea(JTextArea ta){messageLog = ta;}

    /** Makes a move based on learning. */
    public int[] makeMove(Player[][] boardState, int[] lastMove)
    {
    	int[] nextMove = minimax.getNextMove();
    	
    	//update board state based on this move
    	prevState = boardState;
    	updateBoardState(minimax.getModifiedState(boardState, super.getPlayer(), nextMove));
    	
    	//update the 'last move' variable
    	updateLastMove(nextMove);
    	
    	//update the minimax tree - this is very important!
    	//the minimax tree must be updated with a new root once it is our turn again
    	
    	return nextMove;
    }
    
    /** Uses previous board state to determine if opponent's move is optimal */
    public boolean isOptimalMove(int[] opponentMove){
    	//prevState must be the state BEFORE the opponent made their move
    	//Learning AI doesn't give player much credit, assumes he/she is operating on Medium at the moment
    	MinimaxTree opponentTree = new MinimaxTree(prevState, 4, new MinimaxNode(), super.getPlayer());
    	int[] bestMove = opponentTree.getNextMove();
    	
    	//if the computed best move is what the player made, return true
    	if(bestMove[0] == opponentMove[0] && bestMove[1] == opponentMove[1])
    	{
    		return true;
    	}
    	else
    	{
    		return false;
    	}
    }
    
    /** Adjusts the difficulty based on the score */
    public void adjust(int myscore, int opponentscore){
    	//If the opponent is ahead by 7+ points, increase depth
    	if(opponentscore - myscore > 7 && depthAdjust <= 10)
    	{
    		depthAdjust+=2;
    		depthAdjusted=true;
    	}
    }
    
    /** Take in the opponent's turn, and decide if it is an optimal move.  This method adjusts
     * the difficulty level according to learning.  It also updates the minimax tree based on
     * the opponent's move. */
    public void updateMinimax(int[] opponentMove, Player opponentColor)
    {
    	//update board state after opponent move
    	prevState = boardState;
    	updateBoardState(minimax.getModifiedState(boardState, opponentColor, opponentMove));
    	
    	//calculate depth again
    	if(isOptimalMove(opponentMove))
    	{
    		//if the player makes three good moves in a row, difficulty increases
    		//difficulty has a cap at 10 turns ahead
    		if(goodMoves >= 3 && depthAdjust <= 10){
    			goodMoves = 0;
    			depthAdjust+=2;
    			depthAdjusted = true;
    		}
    		messageLog.append(descriptionOfAI());
    	}
    	else
    	{
    		messageLog.append(descriptionOfAI());
    	}
    	
    	depthAdjusted = false;
    	
        //update minimax tree using the current board state
    	minimax = new MinimaxTree(boardState, depthAdjust, new MinimaxNode(), super.getPlayer());
    }
    
    /**
     * Returns a human readable, English language description of the reasoning
     * behind the learning system.
     */
    public String descriptionOfAI() 
    {
    	if(depthAdjusted)
    		return "Difficulty level increased.\n\n";
    	else if(depthAdjust > 10)
    		return "Player has reached maximum difficulty.\n\n";
    	else
    		return "No adjustment made.\n\n";
    }
}

